﻿using System;
using System.Collections;
using System.Collections.Generic;
using Infrastructure.CrossCutting.Extensions;

namespace Infrastructure.CrossCutting.Configuration
{
    public class MultiConfigSource : ConfigSection, IConfigSource
    {
        private readonly IList<IConfigSource> configSources;
        private string sourcePath;
        private string fullName;

        public MultiConfigSource(IList<IConfigSource> sources)
        {
            configSources = sources;
            configSources.ForEach(configSource =>
            {
                configSource.OnConfigSourceChanged += configSource_OnConfigSourceChanged;
                fullName += configSource.Name + ",";
                sourcePath += configSource.SourcePath + ",";
            });
            sourcePath = sourcePath.Replace("/", "\\");
            Merge();
        }

        private void Merge()
        {
            configSources.ForEach(configSource => Merge(configSource, this));
        }

        private static void Merge(IConfigSection source, IConfigSection destination)
        {
            foreach (DictionaryEntry entry in source)
            {
                if (entry.Value is IConfigSection)
                {
                    // create new config section
                    IConfigSection newConfDest;
                    if (destination.Contains(entry.Key))
                        newConfDest = destination.GetSection(entry.Key.ToString());
                    else
                    {
                        newConfDest = new ConfigSection(entry.Key.ToString());
                        destination.Add(newConfDest.Name, newConfDest);
                    }
                    Merge(entry.Value as IConfigSection, newConfDest);
                }
                else
                    destination[entry.Key] = entry.Value;
            }
        }

        void configSource_OnConfigSourceChanged(object sender, EventArgs e)
        {
            //Init();
            //Load();
            Merge();
            ConfigManager.InvokeConfigSourceChangedEventHandler(e);
            //if (OnConfigSourceChanged != null)
            //    OnConfigSourceChanged(sender, e);
        }

        public event EventHandler OnConfigSourceChanged;

        public string SourcePath
        {
            get { return sourcePath; }
        }

        public void Init()
        {
            configSources.ForEach(configSource => configSource.Init());
        }

        public void Load()
        {
            configSources.ForEach(configSource => configSource.Load());
        }

        public void Save()
        {
            configSources.ForEach(configSource => configSource.Save());
        }

        public void ChangeConfigItem(string configItemName, object value)
        {
            configSources.ForEach(configSource =>
            {
                object result;
                if (configSource.TryGet(configItemName, out result))
                {
                    configSource.ChangeConfigItem(configItemName, value);
                }
            });
        }
    }

}
